package com.sec.etech.employeesync.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sec.etech.employeesync.entity.OrgEmployee;
import com.sec.etech.employeesync.entity.OrgEmployeeEducationalExperience;
import com.sec.etech.employeesync.entity.OrgEmployeeNull;
import com.sec.etech.employeesync.entity.OrgEmployeeZSchool;
import com.sec.etech.employeesync.enums.SyncType;
import com.sec.etech.employeesync.mapper.OrgEmployeeMapper;
import com.sec.etech.employeesync.mapper.OrgEmployeeZSchoolMapper;
import com.sec.etech.employeesync.util.EducationalExperienceHandler;
import com.sec.etech.employeesync.util.EmployeeConverter;
import com.sec.etech.employeesync.util.EmployeeFilterHandler;
import com.sec.etech.employeesync.util.MainWorkExperienceHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.openbpm.org.api.model.IUser;
import org.openbpm.sys.util.ContextUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EmployeeSyncService {

    @Resource
    private OrgEmployeeMapper orgEmployeeMapper;
    @Resource
    private EmployeeConverter employeeConverter;
    @Resource
    private EmployeeFilterHandler employeeFilterHandler;
    @Resource
    private MainWorkExperienceHandler mainWorkExperienceHandler;
    @Resource
    private EducationalExperienceHandler educationalExperienceHandler;
    @Autowired
    private OrgEmployeeService orgEmployeeService;
    @Autowired
    private OrgEmployeeNullService orgEmployeeNullService;
    @Resource
    private OrgEmployeeZSchoolMapper schoolMapper;
    @Autowired
    private SchoolService schoolService;

    @Transactional
    public void syncEmployeeData(JSONObject resultObj, SyncType syncType, String companyCode, IUser iUser) {
        ContextUtil.setCurrentUser(iUser);

        JSONObject data = resultObj.getJSONObject("data");
        JSONArray etResultArray = data.getJSONArray("ET_RESULT");
        JSONArray etPa0001Array = data.getJSONArray("ET_PA0001");
        JSONArray etPa9009Array = data.getJSONArray("E_T_PA9009");

//        List<OrgEmployee> newList = getNewEmployeeList(etResultArray);
        List<OrgEmployee> newList = employeeConverter.getNewEmployeeList(etResultArray, iUser);
        List<OrgEmployee> oldList = syncType.sync(new SyncDataContext(orgEmployeeMapper, newList, companyCode));
        List<OrgEmployee> oldAllList = SyncType.FULL.sync(new SyncDataContext(orgEmployeeMapper, newList, companyCode));

//        if (!oldList.isEmpty()) {
//            log.info("oldList数量=====>{}", oldList.size());
//            log.info("oldList=====>{},{}", oldList.get(0).getAccount(), oldList.get(0).getCompanyId());
//        }

        log.info("开始{}同步，公司code：{}, 从SAP拉取到 {} 名员工", syncType, companyCode, newList.size());

        Map<String, OrgEmployee> oldAllEmployeeMap = oldAllList.stream()
                .collect(Collectors.toMap(OrgEmployee::getAccount, Function.identity()));

        List<OrgEmployee> insertList = new ArrayList<>();
        List<OrgEmployee> updateList = new ArrayList<>();

        for (OrgEmployee newEmployee : newList) {
            String account = newEmployee.getAccount();
            OrgEmployee oldEmployee = oldAllEmployeeMap.get(account);
            if (oldEmployee == null) {
                if (syncType != SyncType.SINGLE) {
                    insertList.add(newEmployee);
                } else {
                    throw new IllegalStateException("单个更新模式下，尝试插入新员工");
                }
            } else {
                newEmployee.setEmployeeid(oldEmployee.getEmployeeid());
                newEmployee.setActive(1);
                updateList.add(newEmployee);
            }
        }

        List<OrgEmployee> deleteList = new ArrayList<>();
        if (syncType != SyncType.SINGLE) {
            Set<String> newAccountList = newList.stream()
                    .map(OrgEmployee::getAccount)
                    .collect(Collectors.toSet());

            deleteList = oldList.stream()
                    .filter(e -> e.getActive() == 1)
                    .filter(e -> e.getOrigin() == 1)
                    .filter(e -> !newAccountList.contains(e.getAccount()))
                    .collect(Collectors.toList());
        }

        List<OrgEmployeeNull> orgEmployeeNullList = updateList.parallelStream()
                .map(this::convertToOrgEmployeeNull)
                .collect(Collectors.toList());

//        if (!insertList.isEmpty()) {
//            log.info("本次新增的员工===>{}", insertList.stream().map(OrgEmployee::getAccount).collect(Collectors.toList()));
//        }

        processEmployees(insertList, orgEmployeeNullList, deleteList);
        processMainWorkExperience(insertList, updateList, deleteList, etPa0001Array, iUser);
        processEducationalExperience(insertList, updateList, deleteList, etPa9009Array, iUser);

        updateSchoolFlag(etResultArray);

        log.info("{}同步完成。公司code：{}, 新增: {}, 更新: {}, 删除: {}",
                syncType, companyCode, insertList.size(), updateList.size(), deleteList.size());
    }

    private OrgEmployeeNull convertToOrgEmployeeNull(OrgEmployee orgEmployee) {
        OrgEmployeeNull orgEmployeeNull = new OrgEmployeeNull();
        BeanUtils.copyProperties(orgEmployee, orgEmployeeNull);
        return orgEmployeeNull;
    }

    private void processEmployees(List<OrgEmployee> insertList, List<OrgEmployeeNull> updateList, List<OrgEmployee> deleteList) {
        if (!insertList.isEmpty()) {
            orgEmployeeService.saveBatch(insertList);
            log.info("新增员工数量: {}", insertList.size());
        }

        if (!updateList.isEmpty()) {
            orgEmployeeNullService.updateBatchById(updateList);
            log.info("更新员工数量: {}", updateList.size());
        }

        if (!deleteList.isEmpty()) {
            List<OrgEmployee> logicDeleteList = deleteList.parallelStream()
                    .map(OrgEmployee::getEmployeeid)
                    .map(employeeid -> {
                        OrgEmployee orgEmployee = new OrgEmployee();
                        orgEmployee.setEmployeeid(employeeid);
                        orgEmployee.setActive(0);
                        return orgEmployee;
                    })
                    .collect(Collectors.toList());
            orgEmployeeService.updateBatchById(logicDeleteList);
            log.info("逻辑删除员工数量: {}", deleteList.size());
        }
    }

    private void processMainWorkExperience(List<OrgEmployee> insertList, List<OrgEmployee> updateList,
                                           List<OrgEmployee> deleteList, JSONArray etPa0001Array, IUser iUser) {

        Map<String, JSONArray> mainWorkExperienceMap = etPa0001Array.parallelStream()
                .map(item -> (JSONObject) item)
                .collect(Collectors.groupingBy(
                        item -> item.getString("PERNR"),
                        Collectors.mapping(
                                item -> item,
                                Collectors.toCollection(JSONArray::new)
                        )
                ));

        // 处理新增的员工主业经历
        insertList.parallelStream()
                .forEach(employee -> {
                    JSONArray employeeMainWorkExperience = mainWorkExperienceMap.get(employee.getAccount());
                    if (employeeMainWorkExperience != null && !employeeMainWorkExperience.isEmpty()) {
                        Long employeeid = employee.getEmployeeid();
                        mainWorkExperienceHandler.insertMainWorkExperience(employeeid, employeeMainWorkExperience, iUser);
                    }
                });

        // 处理删除的员工主业经历
//        for (OrgEmployee employee : deleteList) {
//            Long employeeid = employee.getEmployeeid();
//            mainWorkExperienceHandler.deleteMainWorkExperience(employeeid);
//        }

        // 处理更新的员工主业经历
        updateList.parallelStream()
                .forEach(employee -> {
                    JSONArray employeeMainWorkExperience = mainWorkExperienceMap.get(employee.getAccount());

                    if (employeeMainWorkExperience != null && !employeeMainWorkExperience.isEmpty()) {
                        Long employeeId = employee.getEmployeeid();
                        JSONArray collect = employeeMainWorkExperience.parallelStream()
                                .map(item -> (JSONObject) item)
                                .filter(item -> !mainWorkExperienceHandler.checkIfExists(employeeId, item))
                                .collect(Collectors.toCollection(JSONArray::new));

                        mainWorkExperienceHandler.insertMainWorkExperience(employeeId, collect, iUser);
                    }
                });
    }

    private void processEducationalExperience(List<OrgEmployee> insertList, List<OrgEmployee> updateList,
                                              List<OrgEmployee> deleteList, JSONArray etPa9009Array, IUser iUser) {
        if (etPa9009Array == null || etPa9009Array.isEmpty()) {
            return;
        }

        log.info("开始处理教育经历");

        educationalExperienceHandler.preCreateConfig(etPa9009Array, iUser);

        Map<String, JSONArray> educationalExperienceMap = etPa9009Array.stream()
                .map(item -> (JSONObject) item)
                .collect(Collectors.groupingBy(
                        item -> item.getString("PERNR"),
                        Collectors.mapping(
                                item -> item,
                                Collectors.toCollection(JSONArray::new)
                        )
                ));

        // 处理新增的员工教育经历
        insertList.parallelStream()
                .forEach(employee -> {
                    JSONArray educationalExperience = educationalExperienceMap.get(employee.getAccount());
                    if (educationalExperience != null && !educationalExperience.isEmpty()) {
                        Long employeeid = employee.getEmployeeid();

                        List<OrgEmployeeEducationalExperience> list = educationalExperience.parallelStream()
                                .map(obj -> (JSONObject) obj)
                                .map(data -> educationalExperienceHandler.convertToMainWorkExperience(employeeid, data))
                                .collect(Collectors.toList());

                        educationalExperienceHandler.insertEducationalExperience(list, iUser);
                    }
                });

        // 处理更新的员工教育经历
        updateList.parallelStream()
                .forEach(employee -> {
                    JSONArray educationalExperience = educationalExperienceMap.get(employee.getAccount());

                    if (educationalExperience != null && !educationalExperience.isEmpty()) {
                        Long employeeId = employee.getEmployeeid();
                        List<OrgEmployeeEducationalExperience> collect = educationalExperience.parallelStream()
                                .map(item -> (JSONObject) item)
                                .map(item -> educationalExperienceHandler.convertToMainWorkExperience(employeeId, item))
                                .filter(item -> !educationalExperienceHandler.checkIfExists(employeeId, item))
                                .collect(Collectors.toList());

                        educationalExperienceHandler.insertEducationalExperience(collect, iUser);
                    }
                });
    }

    public void updateSchoolFlag(JSONArray jsonArray) {
        List<OrgEmployeeZSchool> schoolList = schoolMapper.selectList(null);
        Map<String, Integer> map = jsonArray.parallelStream()
                .map(item -> (JSONObject) item)
                .filter(item -> StringUtils.isNotBlank(item.getString("ZHRJYBYYX"))
                                && item.getInteger("FLAG_YX") != null)
                .collect(Collectors.toMap(
                                item -> item.getString("ZHRJYBYYX"),
                                item -> item.getInteger("FLAG_YX"),
                                (oldValue, newValue) -> oldValue
                        )
                );

        schoolList.parallelStream()
                .forEach(item -> {
                    Integer flag = map.get(item.getName());
                    if (flag != null) {
                        item.setTag(flag);
                    }
                });

        schoolService.updateBatchById(schoolList);
    }
}
